package gui;

import gui.events.CreateDatabaseEvent;
import gui.events.CreateTableEvent;
import gui.events.DatabasePopupEvent;
import gui.events.TablePopupEvent;
import gui.interfaces.ICreateDatabaseEventListener;
import gui.interfaces.ICreateTableEventListener;
import gui.interfaces.IPopupMenuDatabaseEventListener;
import gui.interfaces.IPopupMenuTableEventListener;
import gui.renderers.DBMSTreeCellRenderer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JSeparator;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.border.EmptyBorder;
import javax.swing.text.Position;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.MutableTreeNode;
import javax.swing.tree.TreePath;

import controller.DatabaseController;
import controller.InitiliazeController;
import controller.TableController;
import dto.ColumnDTO;
import dto.DatabaseIconDTO;
import dto.TableIconDTO;

import javax.swing.JScrollPane;

public class DBMS extends JFrame {

	private JPanel contentPane;
	public static final DefaultMutableTreeNode mockNode = new DefaultMutableTreeNode(
			"Mock Node");

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					DBMS frame = new DBMS();
					frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the frame.
	 */
	/**
	 * 
	 */
	public DBMS() {

		// Using Look-and-Feel Windows for this application.
		try {
			for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager
					.getInstalledLookAndFeels()) {
				if ("Windows".equals(info.getName())) {
					javax.swing.UIManager.setLookAndFeel(info.getClassName());
					break;
				}
			}
		} catch (ClassNotFoundException ex) {
			java.util.logging.Logger.getLogger(DBMS.class.getName()).log(
					java.util.logging.Level.SEVERE, null, ex);
		} catch (InstantiationException ex) {
			java.util.logging.Logger.getLogger(DBMS.class.getName()).log(
					java.util.logging.Level.SEVERE, null, ex);
		} catch (IllegalAccessException ex) {
			java.util.logging.Logger.getLogger(DBMS.class.getName()).log(
					java.util.logging.Level.SEVERE, null, ex);
		} catch (javax.swing.UnsupportedLookAndFeelException ex) {
			java.util.logging.Logger.getLogger(DBMS.class.getName()).log(
					java.util.logging.Level.SEVERE, null, ex);
		}

		setTitle("DBMS Workbench Server");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setBounds(100, 100, 750, 431);
		contentPane = new JPanel();
		contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
		setContentPane(contentPane);
		contentPane.setLayout(new BorderLayout(0, 0));

		JPanel panel = new JPanel();
		JTextArea txtAreaOuput = new JTextArea();
		JList lstResult = new JList();
		JPanel tabOutput = new JPanel();
		JPanel tabResult = new JPanel();
		JTabbedPane tabbedPaneOutput = new JTabbedPane(JTabbedPane.TOP);
		JPanel panelQuery1 = new JPanel();
		final JTabbedPane tabbedPaneQueries = new JTabbedPane(JTabbedPane.TOP);
		JSplitPane splitPane_2 = new JSplitPane();
		JTextArea textArea = new JTextArea();
		final JTree treeDBs;
		JSplitPane splitPane_1 = new JSplitPane();
		JSplitPane splitPane = new JSplitPane();
		JButton btnExecuteQuery = new JButton("");
		JButton btnSave = new JButton("");
		JButton btnOpen = new JButton("");
		JButton btnCreateTable = new JButton("");

		contentPane.add(panel, BorderLayout.NORTH);
		panel.setLayout(new GridLayout(0, 1, 0, 0));

		JMenuBar menuBar = new JMenuBar();
		menuBar.setBorderPainted(false);
		menuBar.setFont(new Font("Segoe UI", Font.PLAIN, 12));
		panel.add(menuBar);

		JMenu mnFile = new JMenu("File");
		menuBar.add(mnFile);

		JMenuItem mntmNewDatabase = new JMenuItem("New Database");
		mnFile.add(mntmNewDatabase);

		JMenuItem mntmNewQuery = new JMenuItem("New Query");
		mnFile.add(mntmNewQuery);

		JMenuItem mntmOpenSqlScript = new JMenuItem("Open SQL Script");
		mnFile.add(mntmOpenSqlScript);

		JSeparator separator = new JSeparator();
		mnFile.add(separator);

		JMenuItem mntmCloseConnection = new JMenuItem("Close connection");
		mnFile.add(mntmCloseConnection);

		JMenuItem mntmCloseTab = new JMenuItem("Close Tab");
		mnFile.add(mntmCloseTab);

		JSeparator separator_1 = new JSeparator();
		mnFile.add(separator_1);

		JMenuItem mntmSaveScript = new JMenuItem("Save script");
		mnFile.add(mntmSaveScript);

		JMenuItem mntmSaveScriptAs = new JMenuItem("Save script as");
		mnFile.add(mntmSaveScriptAs);

		JSeparator separator_2 = new JSeparator();
		mnFile.add(separator_2);

		JMenuItem mntmExit = new JMenuItem("Exit");
		mnFile.add(mntmExit);

		JMenu mnQuery = new JMenu("Query");
		menuBar.add(mnQuery);

		JMenuItem mntmNewQuery_1 = new JMenuItem("New Query");
		mnQuery.add(mntmNewQuery_1);

		JMenuItem mntmExcuteQuery = new JMenuItem("Excute query");
		mnQuery.add(mntmExcuteQuery);

		JMenu mnDatabase = new JMenu("Database");
		menuBar.add(mnDatabase);

		JMenuItem mntmNewDatabase_1 = new JMenuItem("New Database");
		mnDatabase.add(mntmNewDatabase_1);

		JMenuItem mntmDropDatabase = new JMenuItem("Drop database");
		mnDatabase.add(mntmDropDatabase);

		JSeparator separator_4 = new JSeparator();
		mnDatabase.add(separator_4);

		JMenuItem mntmQueryDatabase = new JMenuItem("Query database");
		mnDatabase.add(mntmQueryDatabase);

		JSeparator separator_3 = new JSeparator();
		mnDatabase.add(separator_3);

		JMenuItem mntmManageConnections = new JMenuItem("Manage connections");
		mnDatabase.add(mntmManageConnections);

		JMenu mnHelp = new JMenu("Help");
		menuBar.add(mnHelp);

		JMenuItem mntmAbout = new JMenuItem("About");
		mnHelp.add(mntmAbout);

		JToolBar toolBar = new JToolBar();
		toolBar.setFloatable(false);
		panel.add(toolBar);

		// Button create database
		JButton btnCreateDatabase = new JButton("");
		btnCreateDatabase.setToolTipText("New database");
		btnCreateDatabase.setIcon(new ImageIcon(DBMS.class
				.getResource("images/new-database-icon.png")));
		toolBar.add(btnCreateDatabase);

		// Create Table
		btnCreateTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent arg0) {
				// Button create table's clicked.
				final PanelCreateTable panelCreateTable = new PanelCreateTable();
				panelCreateTable
						.addCreateTableEventListener(new ICreateTableEventListener() {

							@Override
							public void cancel(CreateTableEvent e) {
								// Create is canceled.
								tabbedPaneQueries.remove(panelCreateTable);
							}

							@Override
							public void apply(CreateTableEvent e,
									String dbName, String tableName,
									ArrayList<ColumnDTO> cols) {

								try {
									TableController tableCtrl = new TableController(
											dbName, tableName, cols);
									if (tableCtrl.createTable()) {
										JOptionPane.showMessageDialog(
												tabbedPaneQueries,
												"Create table successful");
										tabbedPaneQueries
												.remove(panelCreateTable);
									}
								} catch (Exception e1) {
									JOptionPane.showMessageDialog(
											tabbedPaneQueries, e1.getMessage());
								}
							}
						});
				tabbedPaneQueries.addTab("new_table", null, panelCreateTable,
						"Create table");
				tabbedPaneQueries.setSelectedComponent(panelCreateTable);
			}
		});
		btnCreateTable.setToolTipText("Create a new table to active database");
		btnCreateTable.setIcon(new ImageIcon(DBMS.class
				.getResource("images/new-table-icon.png")));
		toolBar.add(btnCreateTable);

		/*
		 * OPEN SCRIPT FILE
		 */
		btnOpen.setToolTipText("Open a script file");
		btnOpen.setIcon(new ImageIcon(DBMS.class.getResource("images/open.png")));
		btnOpen.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("Open script file");
			}
		});
		toolBar.add(btnOpen);

		btnSave.setToolTipText("Save script to a file");
		btnSave.setIcon(new ImageIcon(DBMS.class
				.getResource("images/save-icon.png")));
		btnSave.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("Save query");
			}
		});
		toolBar.add(btnSave);

		btnExecuteQuery.setToolTipText("Execute query");
		btnExecuteQuery.setIcon(new ImageIcon(DBMS.class
				.getResource("images/execute-query-icon.png")));
		btnExecuteQuery.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent e) {
				System.out.println("Execute query");
			}
		});
		toolBar.add(btnExecuteQuery);

		splitPane.setResizeWeight(0.15);
		contentPane.add(splitPane, BorderLayout.CENTER);

		splitPane_1.setResizeWeight(0.6);
		splitPane_1.setOrientation(JSplitPane.VERTICAL_SPLIT);
		splitPane.setLeftComponent(splitPane_1);

		// Load all database and show to tree
		InitiliazeController initCtrl = new InitiliazeController();
		ArrayList<DatabaseIconDTO> dbs = initCtrl.getAllDatabaseName();
		DefaultMutableTreeNode nodeDBs = UISupport.processHierarchyTreeNode(dbs
				.toArray());
		treeDBs = new JTree(nodeDBs);

		treeDBs.addMouseListener(new MouseAdapter() {
			private void dbsPopup(MouseEvent e) {
				int x = e.getX();
				int y = e.getY();
				final JTree tree = (JTree) e.getSource();
				TreePath path = tree.getPathForLocation(x, y);
				if (path == null)
					return;
				tree.setSelectionPath(path);
				if (path.getPathCount() == 2) {
					// popup for database's menu
					PopupMenuDatabase popup = new PopupMenuDatabase();
					popup.addPopupDatabaseEventListener(new IPopupMenuDatabaseEventListener() {

						@Override
						public void setAsDefaultDatabase(DatabasePopupEvent e) {
							System.out.println("set as default");
						}

						@Override
						public void refreshAll(DatabasePopupEvent e) {
							// TODO Auto-generated method stub

						}

						@Override
						public void dropDatabase(DatabasePopupEvent e) {
							String dbname = tree.getLastSelectedPathComponent()
									.toString();
							try {
								DatabaseController ctrl = new DatabaseController(
										dbname);
								if (ctrl.dropDatabase() == true) {
									DefaultTreeModel model = (DefaultTreeModel) tree
											.getModel();
									TreePath path2 = tree.getNextMatch(dbname,
											0, Position.Bias.Forward);
									model.removeNodeFromParent((MutableTreeNode) path2
											.getLastPathComponent());
									JOptionPane.showMessageDialog(
											tabbedPaneQueries,
											"Drop successful");
								}
							} catch (Exception e2) {
								JOptionPane.showMessageDialog(
										tabbedPaneQueries, "Drop unsuccessful");
							}
						}

						@Override
						public void alterDatabase(DatabasePopupEvent e) {
						}
					});
					popup.show(tree, x, y);
				} else {
					// popup for table's menu
					PopupMenuTable popup = new PopupMenuTable();
					popup.addPopupTableEventListener(new IPopupMenuTableEventListener() {

						@Override
						public void select1000Rows(TablePopupEvent e) {
							// TODO Auto-generated method stub

						}

						@Override
						public void refreshAll(TablePopupEvent e) {
							// TODO Auto-generated method stub

						}

						@Override
						public void dropTable(TablePopupEvent e) { 
							DefaultMutableTreeNode tblNode = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
							String tableName = ((TableIconDTO)tblNode.getUserObject()).getTableName();
							DefaultMutableTreeNode dbNode = (DefaultMutableTreeNode) tblNode.getParent();
							String dbname = ((DatabaseIconDTO)dbNode.getUserObject()).getDatabaseName();
							try {
								TableController ctrl = new TableController(dbname, tableName);
								if (ctrl.dropTable() == true) {
									DefaultTreeModel model = (DefaultTreeModel) tree
											.getModel();
									model.removeNodeFromParent(tblNode);
									JOptionPane.showMessageDialog(
											tabbedPaneQueries,
											"Drop successful");
								}
							} catch (Exception e2) {
								JOptionPane.showMessageDialog(
										tabbedPaneQueries, "Drop unsuccessful");
							}
						}

						@Override
						public void createTable(TablePopupEvent e) {
							// TODO Auto-generated method stub

						}

						@Override
						public void alterTable(TablePopupEvent e) {
							// TODO Auto-generated method stub

						}
					});
					popup.show(tree, x, y);
				}
			}

			private void dbsDoubleClick(MouseEvent e) {
				int x = e.getX();
				int y = e.getY();
				JTree tree = (JTree) e.getSource();
				TreePath path = tree.getPathForLocation(x, y);
				JPopupMenu popup = new JPopupMenu();
				if (path == null)
					return;
				if (path.getPathCount() == 2) {
					/*
					 * GET TABLE FROM DATABASE
					 */
					// System.out.println("get tables from database here.");
					DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree
							.getLastSelectedPathComponent();
					String dbname = ((DatabaseIconDTO) node.getUserObject())
							.getDatabaseName();
					DatabaseController dbCtrl = new DatabaseController(dbname);
					try {
						// Get table name
						ArrayList<TableIconDTO> tableNames = dbCtrl
								.getAllTableName();
						// Add to treeDBs
						node = (DefaultMutableTreeNode) tree
								.getLastSelectedPathComponent();
						for (TableIconDTO table : tableNames) {
							node.add(new DefaultMutableTreeNode(table));
						}
					} catch (Exception e2) {
						JOptionPane.showMessageDialog(tabbedPaneQueries,
								e2.getMessage());
					}
				}

				tree.setSelectionPath(path);
			}

			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.isPopupTrigger()) {
					dbsPopup(e);
				}
				if (e.getClickCount() == 2) {
					dbsDoubleClick(e);
				}
			}

			@Override
			public void mousePressed(MouseEvent e) {
				if (e.isPopupTrigger()) {
					dbsPopup(e);
				}
			}

			@Override
			public void mouseReleased(MouseEvent e) {
				if (e.isPopupTrigger()) {
					dbsPopup(e);
				}
			}
		});
		splitPane_1.setLeftComponent(treeDBs);
		treeDBs.setRootVisible(false);
		treeDBs.setCellRenderer(new DBMSTreeCellRenderer());

		textArea.setBackground(new Color(224, 255, 255));
		splitPane_1.setRightComponent(textArea);

		splitPane_2.setResizeWeight(0.7);
		splitPane_2.setOrientation(JSplitPane.VERTICAL_SPLIT);
		splitPane.setRightComponent(splitPane_2);

		splitPane_2.setLeftComponent(tabbedPaneQueries);

		tabbedPaneQueries.addTab("Query 1", null, panelQuery1, null);
		panelQuery1.setLayout(new BorderLayout(0, 0));

		JScrollPane scrollPane = new JScrollPane();
		panelQuery1.add(scrollPane, BorderLayout.CENTER);

		JTextArea txtAreaQueryEditor = new JTextArea();
		scrollPane.setViewportView(txtAreaQueryEditor);

		splitPane_2.setRightComponent(tabbedPaneOutput);

		tabbedPaneOutput.addTab("Result", null, tabResult, null);
		tabResult.setLayout(new BorderLayout(0, 0));

		tabResult.add(lstResult, BorderLayout.CENTER);

		tabbedPaneOutput.addTab("Output", null, tabOutput, null);
		tabOutput.setLayout(new BorderLayout(0, 0));

		tabOutput.add(txtAreaOuput, BorderLayout.CENTER);

		// Create database
		btnCreateDatabase.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				// Button Create database's clicked.
				final PanelCreateDatabase panelCreateDatabase = new PanelCreateDatabase();
				panelCreateDatabase
						.addCreateDatabaseEventListener(new ICreateDatabaseEventListener() {
							@Override
							public void cancel(CreateDatabaseEvent e) {
								tabbedPaneQueries.remove(panelCreateDatabase);
							}

							@Override
							public void apply(CreateDatabaseEvent e) {
								// Create database with name
								DatabaseController ctrl = new DatabaseController(
										panelCreateDatabase.getDatbaseName());
								boolean result;
								try {
									result = ctrl.createDatabase();
									if (result) {
										JOptionPane.showMessageDialog(
												panelCreateDatabase,
												"Create successful");
										tabbedPaneQueries
												.remove(panelCreateDatabase);
										InitiliazeController initCtrl = new InitiliazeController();
										ArrayList<DatabaseIconDTO> dbs = initCtrl
												.getAllDatabaseName();
										DefaultMutableTreeNode nodeDBs = UISupport
												.processHierarchyTreeNode(dbs
														.toArray());
										treeDBs.setModel(new DefaultTreeModel(
												nodeDBs));
									}
								} catch (Exception e1) {
									e1.printStackTrace();
									JOptionPane.showMessageDialog(
											panelCreateDatabase,
											e1.getMessage());
								}
							}
						});
				panelCreateDatabase.setVisible(true);
				tabbedPaneQueries.addTab("Create database", null,
						panelCreateDatabase, "Create database");
				tabbedPaneQueries.setSelectedComponent(panelCreateDatabase);

			}
		});
	}
}
